home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Toolbox / Visual Basic Toolbox (P.I.E.)(1996).ISO / disk_utl / qsetup / setup1.bas < prev   
Encoding:
BASIC Source File  |  1994-12-29  |  29.5 KB  |  841 lines

  1. Declare Function GetPrivateProfileString Lib "Kernel" (ByVal lpAppName$, ByVal lpKeyName$, ByVal lpDefault$, ByVal lpRetString$, ByVal nSize%, ByVal lpFileName$) As Integer
  2.  
  3. Sub AddShareIfNeeded (SharePath$, ShareFile$)
  4.     On Error GoTo ShareError
  5.  
  6.     fh% = FreeFile
  7.     Open "C:\AUTOEXEC.BAT" For Input As fh%
  8.  
  9.     fFound% = 0
  10.     While Not fFound% And Not EOF(fh%)
  11.     Line Input #fh%, Temp1$
  12.     If InStr(1, UCase$(Temp1$), "REM") = 0 And InStr(1, Temp1$, ";") = 0 And InStr(1, UCase$(Temp1$), "SHARE") > 0 Then
  13.        fFound% = True
  14.     End If
  15.     Wend
  16.  
  17.     Close #fh%
  18.  
  19.     If Not fFound% Then
  20.     MsgBox "Please add <PATH>SHARE.EXE /L:500 to your AUTOEXEC.BAT"
  21.     End If
  22.  
  23.     Exit Sub
  24. ShareError:
  25.     Close #fh%, #fh2%
  26.     Exit Sub
  27. End Sub
  28.  
  29. '-------------------------------------------------------
  30. ' Centers the passed form just above center on the screen
  31. '-------------------------------------------------------
  32. Sub CenterForm (x As Form)
  33.   
  34.     Screen.MousePointer = 11
  35.     x.Top = (Screen.Height * .85) / 2 - x.Height / 2
  36.     x.Left = Screen.Width / 2 - x.Width / 2
  37.     Screen.MousePointer = 0
  38.  
  39. End Sub
  40.  
  41. Sub ConcatSplitFiles (firstfile$, cSplit%)
  42.     Dim x%, fh1%, fh2%, outfile$, outfileLen&, CopyLeftOver&, CopyChunk#, filevar$
  43.     Dim iFileMax%, iFile%, y%
  44.  
  45.     For x% = 2 To cSplit%
  46.     
  47.     fh1% = FreeFile
  48.     Open Left$(firstfile$, Len(firstfile$) - 1) + Format$(1) For Binary As fh1%
  49.         
  50.     fh2% = FreeFile
  51.     outfile$ = Left$(firstfile$, Len(firstfile$) - 1) + Format$(x%)
  52.     Open outfile$ For Binary As fh2%
  53.         
  54.     ' Goto the end of file (plus one bytes) to start writing data
  55.     Seek #fh1%, LOF(fh1%) + 1
  56.  
  57.     outfileLen& = LOF(fh2%)
  58.     CopyLeftOver& = outfileLen& Mod 10
  59.     CopyChunk# = (outfileLen& - CopyLeftOver&) / 10
  60.     filevar$ = String$(CopyLeftOver&, 32)
  61.     Get #fh2%, , filevar$
  62.     Put #fh1%, , filevar$
  63.     filevar$ = String$(CopyChunk#, 32)
  64.     iFileMax% = 10
  65.     For iFile% = 1 To iFileMax%
  66.         Get #fh2%, , filevar$
  67.         Put #fh1%, , filevar$
  68.     Next iFile%
  69.  
  70.     Close fh1%, fh2%
  71.     y% = SetTime(outfile$, firstfile$)
  72.     Kill outfile$
  73.  
  74.     Next x%
  75.     
  76.     FileCopy Left$(firstfile$, Len(firstfile$) - 1) + Format$(1), firstfile$
  77.     Kill Left$(firstfile$, Len(firstfile$) - 1) + Format$(1)
  78. End Sub
  79.  
  80. '---------------------------------------------------------------
  81. ' Copies file SrcFilename from SourcePath to DestinationPath.
  82. '
  83. ' Returns 0 if it could not find the file, or other runtime
  84. ' error occurs.  Otherwise, returns true.
  85. '
  86. ' If the source file is older, the function returns success (-1)
  87. ' even though no file was copied, since no error occurred.
  88. '---------------------------------------------------------------
  89. Function CopyFile (ByVal SourcePath As String, ByVal DestinationPath As String, ByVal SrcFilename As String, ByVal DestFileName As String)
  90. ' ----- VerInstallFile() flags -----
  91.     Const VIFF_FORCEINSTALL% = &H1, VIFF_DONTDELETEOLD% = &H2
  92.     Const OF_DELETE% = &H200
  93.     Const VIF_TEMPFILE& = &H1
  94.     Const VIF_MISMATCH& = &H2
  95.     Const VIF_SRCOLD& = &H4
  96.  
  97.     Const VIF_DIFFLANG& = &H8
  98.     Const VIF_DIFFCODEPG& = &H10
  99.     Const VIF_DIFFTYPE& = &H20
  100.     Const VIF_WRITEPROT& = &H40
  101.     Const VIF_FILEINUSE& = &H80
  102.     Const VIF_OUTOFSPACE& = &H100
  103.     Const VIF_ACCESSVIOLATION& = &H200
  104.     Const VIF_SHARINGVIOLATION = &H400
  105.     Const VIF_CANNOTCREATE = &H800
  106.     Const VIF_CANNOTDELETE = &H1000
  107.     Const VIF_CANNOTRENAME = &H2000
  108.     Const VIF_CANNOTDELETECUR = &H4000
  109.     Const VIF_OUTOFMEMORY = &H8000
  110.  
  111.     Const VIF_CANNOTREADSRC = &H10000
  112.     Const VIF_CANNOTREADDST = &H20000
  113.  
  114.     Const VIF_BUFFTOOSMALL = &H40000
  115.     Dim TmpOFStruct As OFStruct
  116.     On Error GoTo ErrorCopy
  117.  
  118.     Screen.MousePointer = 11
  119.  
  120.     '--------------------------------------
  121.     ' Add ending \ symbols to path variables
  122.     '--------------------------------------
  123.     If Right$(SourcePath$, 1) <> "\" Then
  124.     SourcePath$ = SourcePath$ + "\"
  125.     End If
  126.     If Right$(DestinationPath$, 1) <> "\" Then
  127.     DestinationPath$ = DestinationPath$ + "\"
  128.     End If
  129.     
  130.     '----------------------------
  131.     ' Update status dialog info
  132.     '----------------------------
  133.     Statusdlg.Label1.Caption = "Source file: " + Chr$(10) + Chr$(13) + UCase$(SourcePath$ + SrcFilename$)
  134.     Statusdlg.Label1.Refresh
  135.     Statusdlg.Label2.Caption = "Destination file: " + Chr$(10) + Chr$(13) + UCase$(DestinationPath$ + DestFileName$)
  136.     Statusdlg.Label2.Refresh
  137.  
  138.     '-----------------------------------------
  139.     ' Check the validity of the path and file
  140.     '-----------------------------------------
  141. CheckForExist:
  142.     If Not FileExists(SourcePath$ + SrcFilename$) Then
  143.     Screen.MousePointer = 0
  144.     x% = MsgBox("Error occurred while attempting to copy file.  Could not locate file: """ + SourcePath$ + SrcFilename$ + """", 34, "SETUP")
  145.     Screen.MousePointer = 11
  146.     If x% = 3 Then
  147.         CopyFile = False
  148.     ElseIf x% = 4 Then
  149.         GoTo CheckForExist
  150.     ElseIf x% = 5 Then
  151.         GoTo SkipThisFile
  152.     End If
  153.     Else
  154.     '--------------------------------------------------------------'
  155.     ' VerInstallFile installs the file. We need to initialize      '
  156.     ' some arguments for the temp file that is created by the call '
  157.     '--------------------------------------------------------------'
  158. TryToCopyAgain:
  159.     CurrDir$ = String$(255, 0)
  160.     TmpFile$ = String$(255, 0)
  161.     lpwTempFileLen% = 255
  162.     ' If the destination file does not exist, do not waste time      '
  163.     ' in version checking logic, go right to the copy routine.       '
  164.     If Not FileExists(DestinationPath$ + DestFileName$) Then
  165.         GoTo SkipVerCheck
  166.     End If
  167.     ' Version stamp retrieval takes a long time especially on floppy '
  168.     ' disks, use optional GetInFileVersion function.                 '
  169.     InFileVer$ = GetInFileVersion(SourcePath$, SrcFilename$)
  170.     ' Use original routine for destination file search which isn't   '
  171.     ' to slow on hard disk files.                                    '
  172.     OutFileVer$ = GetFileVersion(DestinationPath$ + DestFileName$)
  173.     ' Install if no version info is available                        '
  174.     If Len(InFileVer$) <> 0 And Len(OutFileVer$) <> 0 Then
  175.         ' Don't install older or same version of file
  176.         If InFileVer$ <= OutFileVer$ Then
  177.         UpdateStatus GetFileSize(SourcePath$ + SrcFilename$)
  178.         CopyFile = True
  179.         Exit Function
  180.         End If
  181.     End If
  182. SkipVerCheck:
  183.     Result& = VerInstallFile&(0, SrcFilename$, DestFileName$, SourcePath$, DestinationPath$, CurrDir$, TmpFile$, lpwTempFileLen%)
  184.  
  185.     '--------------------------------------------
  186.     ' After copying, update the installation meter
  187.     '---------------------------------------------
  188.     
  189.     S$ = DestinationPath$
  190.     If Right$(S$, 1) <> "\" Then S$ = S$ + "\"
  191.     S$ = S$ + DestFileName$
  192.     If Not TryAgain% Then UpdateStatus GetFileSize(S$)
  193.  
  194.     '--------------------------------
  195.     ' There are many return values that you can test for.
  196.     ' The constants are listed above.
  197.     ' The following lines of code return will set the Function to
  198.     ' True if the VerInstallFile call was successful.
  199.     '
  200.     ' If the call was unsuccessful due to a different language on the
  201.     ' users machine, VerInstallFile is called again to force installation.
  202.     ' You can change this to not install if you choose.
  203.     ' Be careful about using FORCEINSTALL.  Other flags could be
  204.     ' set which indicate that this file should not be overridden.
  205.     '
  206.     ' Under any other circumstance, the tempfile created by VerInstallFile
  207.     ' is removed using OpenFile and the CopyFile function returns false.
  208.     '--------------------------------------------------------
  209.     
  210.     If Result& = 0 Or (Result& And VIF_SRCOLD&) = VIF_SRCOLD& Then
  211.         CopyFile = True
  212.     ElseIf (Result& And VIF_DIFFLANG&) = VIF_DIFFLANG& Then
  213.         Result& = VerInstallFile&(VIFF_FORCEINSTALL%, SrcFilename$, DestFileName$, SourcePath$, DestinationPath$, CurrDir$, TmpFile$, lpwTempFileLen%)
  214.         CopyFile = True
  215.     ElseIf (Result& And VIF_WRITEPROT&) = VIF_WRITEPROT& Then
  216.         Result& = VerInstallFile&(VIFF_FORCEINSTALL%, SrcFilename$, DestFileName$, SourcePath$, winSysDir$ + "\", CurrDir$, TmpFile$, lpwTempFileLen%)
  217.         CopyFile = True
  218.     ElseIf (Result& And VIF_CANNOTREADSRC) = VIF_CANNOTREADSRC Then
  219.         ' VerInstallFile does will not handle compressed files that have been split.
  220.         ' Use VB's FileCopy stmt
  221.         FileCopy SourcePath$ + SrcFilename$, DestinationPath$ + DestFileName$
  222.         CopyFile = True
  223.     Else
  224.         Screen.MousePointer = 0
  225.         If (Result& And VIF_FILEINUSE&) = VIF_FILEINUSE& Then
  226.         x% = MsgBox(DestFileName$ & " is in use. Please close all applications and re-attempt Setup.", 34)
  227.         If x% = 3 Then
  228.             CopyFile = False
  229.         ElseIf x% = 4 Then
  230.             TryAgain% = True
  231.             GoTo TryToCopyAgain
  232.         ElseIf x% = 5 Then
  233.             CopyFile = True
  234.             GoTo SkipThisFile
  235.         End If
  236.         Else
  237.         MsgBox DestFileName$ & " could not be installed."
  238.         CopyFile = False
  239.         End If
  240.         Screen.MousePointer = 11
  241.     End If
  242.  
  243.     If (Result& And VIF_TEMPFILE&) = VIF_TEMPFILE& Then copyresult% = OpenFile(TmpFile$, TmpOFStruct, OF_DELETE%)
  244.        Screen.MousePointer = 0
  245.        Exit Function
  246.     End If
  247.  
  248. SkipThisFile:
  249.        Exit Function
  250. ErrorCopy:
  251.     CopyFile = False
  252.     Screen.MousePointer = 0
  253.     Exit Function
  254.  
  255. End Function
  256.  
  257. '---------------------------------------------
  258. ' Create the path contained in DestPath$
  259. ' First char must be drive letter, followed by
  260. ' a ":\" followed by the path, if any.
  261. '---------------------------------------------
  262. Function CreatePath (ByVal DestPath$) As Integer
  263.     Screen.MousePointer = 11
  264.  
  265.     '---------------------------------------------
  266.     ' Add slash to end of path if not there already
  267.     '---------------------------------------------
  268.     If Right$(DestPath$, 1) <> "\" Then
  269.     DestPath$ = DestPath$ + "\"
  270.     End If
  271.       
  272.  
  273.     '-----------------------------------
  274.     ' Change to the root dir of the drive
  275.     '-----------------------------------
  276.     On Error Resume Next
  277.     ChDrive DestPath$
  278.     If Err <> 0 Then GoTo errorOut
  279.     ChDir "\"
  280.  
  281.     '-------------------------------------------------
  282.     ' Attempt to make each directory, then change to it
  283.     '-------------------------------------------------
  284.     BackPos = 3
  285.     forePos = InStr(4, DestPath$, "\")
  286.     Do While forePos <> 0
  287.     temp$ = Mid$(DestPath$, BackPos + 1, forePos - BackPos - 1)
  288.  
  289.     Err = 0
  290.     MkDir temp$
  291.     If Err <> 0 And Err <> 75 Then GoTo errorOut
  292.  
  293.     Err = 0
  294.     ChDir temp$
  295.     If Err <> 0 Then GoTo errorOut
  296.  
  297.     BackPos = forePos
  298.     forePos = InStr(BackPos + 1, DestPath$, "\")
  299.     Loop
  300.          
  301.     CreatePath = True
  302.     Screen.MousePointer = 0
  303.     Exit Function
  304.          
  305. errorOut:
  306.     MsgBox "Error While Attempting to Create Directories on Destination Drive.", 48, "SETUP"
  307.     CreatePath = False
  308.     Screen.MousePointer = 0
  309.  
  310. End Function
  311.  
  312. '-------------------------------------------------------------
  313. ' Procedure: CreateProgManGroup
  314. ' Arguments: X           The Form where a Label1 exist
  315. '            GroupName$  A string that contains the group name
  316. '            GroupPath$  A string that contains the group file
  317. '                        name  ie 'myapp.grp'
  318. '-------------------------------------------------------------
  319. Sub CreateProgManGroup (x As Form, GroupName$, GroupPath$)
  320.     
  321.     Screen.MousePointer = 11
  322.     
  323.     '----------------------------------------------------------------------
  324.     ' Windows requires DDE in order to create a program group and item.
  325.     ' Here, a Visual Basic label control is used to generate the DDE messages
  326.     '----------------------------------------------------------------------
  327.     On Error Resume Next
  328.  
  329.     
  330.     '--------------------------------
  331.     ' Set LinkTopic to PROGRAM MANAGER
  332.     '--------------------------------
  333.     x.Label1.LinkTopic = "ProgMan|Progman"
  334.     x.Label1.LinkMode = 2
  335.     For i% = 1 To 10                                         ' Loop to ensure that there is enough time to
  336.       z% = DoEvents()                                        ' process DDE Execute.  This is redundant but needed
  337.     Next                                                     ' for debug windows.
  338.     x.Label1.LinkTimeout = 100
  339.  
  340.  
  341.     '---------------------
  342.     ' Create program group
  343.     '---------------------
  344.     x.Label1.LinkExecute "[CreateGroup(" + GroupName$ + Chr$(44) + GroupPath$ + ")]"
  345.  
  346.  
  347.     '-----------------
  348.     ' Reset properties
  349.     '-----------------
  350.     x.Label1.LinkTimeout = 50
  351.     x.Label1.LinkMode = 0
  352.     
  353.     Screen.MousePointer = 0
  354. End Sub
  355.  
  356. '----------------------------------------------------------
  357. ' Procedure: CreateProgManItem
  358. '
  359. ' Arguments: X           The form where Label1 exists
  360. '
  361. '            CmdLine$    A string that contains the command
  362. '                        line for the item/icon.
  363. '                        ie 'c:\myapp\setup.exe'
  364. '
  365. '            IconTitle$  A string that contains the item's
  366. '                        caption
  367. '----------------------------------------------------------
  368. Sub CreateProgManItem (x As Form, CmdLine$, IconTitle$)
  369.     
  370.     Screen.MousePointer = 11
  371.     
  372.     '----------------------------------------------------------------------
  373.     ' Windows requires DDE in order to create a program group and item.
  374.     ' Here, a Visual Basic label control is used to generate the DDE messages
  375.     '----------------------------------------------------------------------
  376.     On Error Resume Next
  377.  
  378.  
  379.     '---------------------------------
  380.     ' Set LinkTopic to PROGRAM MANAGER
  381.     '---------------------------------
  382.     x.Label1.LinkTopic = "ProgMan|Progman"
  383.     x.Label1.LinkMode = 2
  384.     For i% = 1 To 10                                         ' Loop to ensure that there is enough time to
  385.       z% = DoEvents()                                        ' process DDE Execute.  This is redundant but needed
  386.     Next                                                     ' for debug windows.
  387.     x.Label1.LinkTimeout = 100
  388.  
  389.     
  390.     '------------------------------------------------
  391.     ' Create Program Item, one of the icons to launch
  392.     ' an application from Program Manager
  393.     '------------------------------------------------
  394.     If gfWin31% Then
  395.     ' Win 3.1 has a ReplaceItem, which will allow us to replace existing icons
  396.     x.Label1.LinkExecute "[ReplaceItem(" + IconTitle$ + ")]"
  397.     End If
  398.     x.Label1.LinkExecute "[AddItem(" + CmdLine$ + Chr$(44) + IconTitle$ + Chr$(44) + ",,)]"
  399.     x.Label1.LinkExecute "[ShowGroup(groupname, 1)]"         ' This will ensure that Program Manager does not
  400.                                  ' have a Maximized group, which causes problem in RestoreProgMan
  401.  
  402.     '-----------------
  403.     ' Reset properties
  404.     '-----------------
  405.     x.Label1.LinkTimeout = 50
  406.     x.Label1.LinkMode = 0
  407.     
  408.     Screen.MousePointer = 0
  409. End Sub
  410.  
  411. '----------------------------------------------------------
  412. ' Check for the existence of a file by attempting an OPEN.
  413. '----------------------------------------------------------
  414. Function FileExists (path$) As Integer
  415.  
  416.     x = FreeFile
  417.  
  418.     On Error Resume Next
  419.     Open path$ For Input As x
  420.     If Err = 0 Then
  421.     FileExists = True
  422.     Else
  423.     FileExists = False
  424.     End If
  425.     Close x
  426.  
  427. End Function
  428.  
  429. '------------------------------------------------
  430. ' Get the disk space free for the current drive
  431. '------------------------------------------------
  432. Function GetDiskSpaceFree (drive As String) As Long
  433.     ChDrive drive
  434.     GetDiskSpaceFree = DiskSpaceFree()
  435. End Function
  436.  
  437. '----------------------------------------------------
  438. ' Get the disk Allocation unit for the current drive
  439. '----------------------------------------------------
  440. Function GetDrivesAllocUnit (drive As String) As Long
  441.     ChDrive drive
  442.     GetDrivesAllocUnit = AllocUnit()
  443. End Function
  444.  
  445. '------------------------
  446. ' Get the size of the file
  447. '------------------------
  448. Function GetFileSize (source$) As Long
  449.     x = FreeFile
  450.     Open source$ For Binary Access Read As x
  451.     GetFileSize = LOF(x)
  452.     Close x
  453. End Function
  454.  
  455. Function GetFileVersion (FileToCheck As String) As String
  456.     On Error Resume Next
  457.     VersionInfoSize& = GetFileVersionInfoSize(FileToCheck, lpdwHandle&)
  458.     If VersionInfoSize& = 0 Then
  459.     GetFileVersion = ""
  460.     Exit Function
  461.     End If
  462.     lpvdata$ = String(VersionInfoSize&, Chr$(0))
  463.     VersionInfo% = GetFileVersionInfo(FileToCheck, lpdwHandle&, VersionInfoSize&, lpvdata$)
  464.     ptrFixed% = VerQueryValue(lpvdata$, "\FILEVERSION", lplpBuffer&, lpcb%)
  465.     If ptrFixed% = 0 Then
  466.     ' Take a shot with the hardcoded TransString
  467.     TransString$ = "040904E4"
  468.     ptrString% = VerQueryValue(lpvdata$, "\StringFileInfo\" & TransString$ & "\CompanyName", lplpBuffer&, lpcb%)
  469.     If ptrString% <> 0 Then GoTo GetValues
  470.     ptrFixed% = VerQueryValue(lpvdata$, "\", lplpBuffer&, lpcb%)
  471.     If ptrFixed% = 0 Then
  472.         GetFileVersion = ""
  473.         Exit Function
  474.     Else
  475.         TransString$ = ""
  476.         fixedstr$ = String(lpcb% + 1, Chr(0))
  477.         stringcopy& = lstrcpyn(fixedstr$, lplpBuffer&, lpcb% + 1)
  478.         For i = lpcb% To 1 Step -1
  479.         char$ = Hex(Asc(Mid(fixedstr$, i, 1)))
  480.         If Len(char$) = 1 Then
  481.             char$ = "0" + char$
  482.         End If
  483.         TransString$ = TransString$ + char$
  484.         If Len(TransString$ & nextchar$) Mod 8 = 0 Then
  485.             TransString$ = "&H" & TransString$
  486.             TransValue& = Val(TransString$)
  487.             TransString$ = ""
  488.         End If
  489.         Next i
  490.     End If
  491.     End If
  492.     TransTable$ = String(lpcb% + 1, Chr(0))
  493.     TransString$ = String(0, Chr(0))
  494.     stringcopy& = lstrcpyn(TransTable$, lplpBuffer&, lpcb% + 1)
  495.     For i = 1 To lpcb%
  496.     char$ = Hex(Asc(Mid(TransTable$, i, 1)))
  497.     If Len(char$) = 1 Then
  498.         char$ = "0" + char$
  499.     End If
  500.     If Len(TransString$ & nextchar$) Mod 4 = 0 Then
  501.         nextchar$ = char$
  502.     Else
  503.         TransString$ = TransString$ + char$ + nextchar$
  504.         nextchar$ = ""
  505.         char$ = ""
  506.     End If
  507.     Next i
  508. GetValues:
  509.     ptrString% = VerQueryValue(lpvdata$, "\StringFileInfo\" & TransString$ & "\FileVersion", lplpBuffer&, lpcb%)
  510.     If ptrString% = 1 Then
  511.     TransTable$ = String(lpcb%, Chr(0))
  512.     stringcopy& = lstrcpyn(TransTable$, lplpBuffer&, lpcb% + 1)
  513.     GetFileVersion = TransTable$
  514.     Else
  515.     GetFileVersion = ""
  516.     End If
  517. End Function
  518.  
  519. Function GetInFileVersion (SourcePath As String, FileToCheck As String) As String
  520.     On Error Resume Next
  521.     '                                                           '
  522.     ' This routine will pull file version numbers from the      '
  523.     ' FILEVERS.LOG file if it is present on the distribution    '
  524.     ' diskette.  This function should be called to obtain ver-  '
  525.     ' sion numbers for files on your distribution diskettes.    '
  526.     '                                                           '
  527.     ' The file must be an INI file format that looks like this: '
  528.     '                                                           '
  529.     ' [File Versions]                                           '
  530.     ' MSABC200.DL_=version#                                     '
  531.     ' MSAJT200.DL_=version#                                     '
  532.     ' THREED.VB_=version#                                       '
  533.     ' SOMEFILE.VB_=version#                                     '
  534.     ' MYPGM.EX_=none                                            '
  535.     ' MYPGM.IN_=none                                            '
  536.     '                                                           '
  537.     ' Be sure that every file on each distribution diskette is  '
  538.     ' included in the FILEVERS.LOG file.  Each diskette must    '
  539.     ' include its own unique FILEVERS.LOG file with entries for '
  540.     ' each file on the diskette.                                '
  541.     '                                                           '
  542.     ' The format of version# must be exactly the same as that   '
  543.     ' returned by the GetFileVersion function.  This routine    '
  544.     ' is MUCH faster than scanning a file on a diskette for the '
  545.     ' version number.  If the .log file doesn't exist then the  '
  546.     ' original GetFileVersion function will be called causing   '
  547.     ' a time-consuming file scan.  If a file entry is missing   '
  548.     ' from the log file then the original function will also    '
  549.     ' be called.                                                '
  550.     '                                                           '
  551.     Dim lRc As Integer
  552.     Dim lVerLogFile As String
  553.     Dim lValue As String
  554.     '                                                           '
  555.     lVerLogFile = SourcePath + "FILEVERS.LOG"
  556.     If FileExists(lVerLogFile) Then
  557.     lValue = String$(255, 32)
  558.     lRc = GetPrivateProfileString("File Versions", FileToCheck, "", lValue, Len(lValue), lVerLogFile)
  559.     lValue = Mid$(lValue, 1, lRc)
  560.     If lValue = "" Then                              ' file not in log
  561.         GetInFileVersion = GetFileVersion(SourcePath + FileToCheck)
  562.     ElseIf lValue = "none" Then                      ' file doesn't contain version stamp
  563.         GetInFileVersion = ""
  564.     Else                                             ' version # found in log
  565.         GetInFileVersion = lValue
  566.     End If
  567.     Else
  568.     GetInFileVersion = GetFileVersion(SourcePath + FileToCheck)
  569.     End If
  570.     '                                                           '
  571. End Function
  572.  
  573. '--------------------------------------------------
  574. ' Calls the windows API to get the windows directory
  575. '--------------------------------------------------
  576. Function GetWindowsDir () As String
  577.     temp$ = String$(145, 0)              ' Size Buffer
  578.     x = GetWindowsDirectory(temp$, 145)  ' Make API Call
  579.     temp$ = Left$(temp$, x)              ' Trim Buffer
  580.  
  581.     If Right$(temp$, 1) <> "\" Then      ' Add \ if necessary
  582.     GetWindowsDir$ = temp$ + "\"
  583.     Else
  584.     GetWindowsDir$ = temp$
  585.     End If
  586. End Function
  587.  
  588. '---------------------------------------------------------
  589. ' Calls the windows API to get the windows\SYSTEM directory
  590. '---------------------------------------------------------
  591. Function GetWindowsSysDir () As String
  592.     temp$ = String$(145, 0)                 ' Size Buffer
  593.     x = GetSystemDirectory(temp$, 145)      ' Make API Call
  594.     temp$ = Left$(temp$, x)                 ' Trim Buffer
  595.  
  596.     If Right$(temp$, 1) <> "\" Then         ' Add \ if necessary
  597.     GetWindowsSysDir$ = temp$ + "\"
  598.     Else
  599.     GetWindowsSysDir$ = temp$
  600.     End If
  601. End Function
  602.  
  603. '------------------------------------------------------
  604. ' Function:   IsValidPath as integer
  605. ' arguments:  DestPath$         a string that is a full path
  606. '             DefaultDrive$     the default drive.  eg.  "C:"
  607. '
  608. '  If DestPath$ does not include a drive specification,
  609. '  IsValidPath uses Default Drive
  610. '
  611. '  When IsValidPath is finished, DestPath$ is reformated
  612. '  to the format "X:\dir\dir\dir\"
  613. '
  614. ' Result:  True (-1) if path is valid.
  615. '          False (0) if path is invalid
  616. '-------------------------------------------------------
  617. Function IsValidPath (DestPath$, ByVal DefaultDrive$) As Integer
  618.  
  619.     '----------------------------
  620.     ' Remove left and right spaces
  621.     '----------------------------
  622.     DestPath$ = RTrim$(LTrim$(DestPath$))
  623.     
  624.  
  625.     '-----------------------------
  626.     ' Check Default Drive Parameter
  627.     '-----------------------------
  628.     If Right$(DefaultDrive$, 1) <> ":" Or Len(DefaultDrive$) <> 2 Then
  629.     MsgBox "Bad default drive parameter specified in IsValidPath Function.  You passed,  """ + DefaultDrive$ + """.  Must be one drive letter and "":"".  For example, ""C:"", ""D:""...", 64, "Setup Kit Error"
  630.     GoTo parseErr
  631.     End If
  632.     
  633.  
  634.     '-------------------------------------------------------
  635.     ' Insert default drive if path begins with root backslash
  636.     '-------------------------------------------------------
  637.     If Left$(DestPath$, 1) = "\" Then
  638.     DestPath$ = DefaultDrive + DestPath$
  639.     End If
  640.     
  641.     '-----------------------------
  642.     ' check for invalid characters
  643.     '-----------------------------
  644.     On Error Resume Next
  645.     tmp$ = Dir$(DestPath$)
  646.     If Err <> 0 Then
  647.     GoTo parseErr
  648.     End If
  649.     
  650.  
  651.     '-----------------------------------------
  652.     ' Check for wildcard characters and spaces
  653.     '-----------------------------------------
  654.     If (InStr(DestPath$, "*") <> 0) GoTo parseErr
  655.     If (InStr(DestPath$, "?") <> 0) GoTo parseErr
  656.     If (InStr(DestPath$, " ") <> 0) GoTo parseErr
  657.      
  658.     
  659.     '------------------------------------------
  660.     ' Make Sure colon is in second char position
  661.     '------------------------------------------
  662.     If Mid$(DestPath$, 2, 1) <> Chr$(58) Then GoTo parseErr
  663.     
  664.  
  665.     '-------------------------------
  666.     ' Insert root backslash if needed
  667.     '-------------------------------
  668.     If Len(DestPath$) > 2 Then
  669.       If Right$(Left$(DestPath$, 3), 1) <> "\" Then
  670.     DestPath$ = Left$(DestPath$, 2) + "\" + Right$(DestPath$, Len(DestPath$) - 2)
  671.       End If
  672.     End If
  673.  
  674.     '-------------------------
  675.     ' Check drive to install on
  676.     '-------------------------
  677.     drive$ = Left$(DestPath$, 1)
  678.     ChDrive (drive$)                                                        ' Try to change to the dest drive
  679.     If Err <> 0 Then GoTo parseErr
  680.     
  681.     '-----------
  682.     ' Add final \
  683.     '-----------
  684.     If Right$(DestPath$, 1) <> "\" Then
  685.     DestPath$ = DestPath$ + "\"
  686.     End If
  687.     
  688.  
  689.     '-------------------------------------
  690.     ' Root dir is a valid dir
  691.     '-------------------------------------
  692.     If Len(DestPath$) = 3 Then
  693.     If Right$(DestPath$, 2) = ":\" Then
  694.         GoTo ParseOK
  695.     End If
  696.     End If
  697.     
  698.  
  699.     '------------------------
  700.     ' Check for repeated Slash
  701.     '------------------------
  702.     If InStr(DestPath$, "\\") <> 0 Then GoTo parseErr
  703.     
  704.     '--------------------------------------
  705.     ' Check for illegal directory names
  706.     '--------------------------------------
  707.     legalChar$ = "!#$%&'()-0123456789@ABCDEFGHIJKLMNOPQRSTUVWXYZ^_`{}~.ⁿΣ÷─╓▄▀"
  708.     BackPos = 3
  709.     forePos = InStr(4, DestPath$, "\")
  710.     Do
  711.     temp$ = Mid$(DestPath$, BackPos + 1, forePos - BackPos - 1)
  712.     
  713.     '----------------------------
  714.     ' Test for illegal characters
  715.     '----------------------------
  716.     For i = 1 To Len(temp$)
  717.         If InStr(legalChar$, UCase$(Mid$(temp$, i, 1))) = 0 Then GoTo parseErr
  718.     Next i
  719.  
  720.     '-------------------------------------------
  721.     ' Check combinations of periods and lengths
  722.     '-------------------------------------------
  723.     periodPos = InStr(temp$, ".")
  724.     length = Len(temp$)
  725.     If periodPos = 0 Then
  726.         If length > 8 Then GoTo parseErr                         ' Base too long
  727.     Else
  728.         If periodPos > 9 Then GoTo parseErr                      ' Base too long
  729.         If length > periodPos + 3 Then GoTo parseErr             ' Extension too long
  730.         If InStr(periodPos + 1, temp$, ".") <> 0 Then GoTo parseErr' Two periods not allowed
  731.     End If
  732.  
  733.     BackPos = forePos
  734.     forePos = InStr(BackPos + 1, DestPath$, "\")
  735.     Loop Until forePos = 0
  736.  
  737. ParseOK:
  738.     IsValidPath = True
  739.     Exit Function
  740.  
  741. parseErr:
  742.     IsValidPath = False
  743. End Function
  744.  
  745. '----------------------------------------------------
  746. ' Prompt for the next disk.  Use the FileToLookFor$
  747. ' argument to verify that the proper disk, disk number
  748. ' wDiskNum, was inserted.
  749. '----------------------------------------------------
  750. Function PromptForNextDisk (wDiskNum As Integer, FileToLookFor$) As Integer
  751.  
  752.     '-------------------------
  753.     ' Test for file
  754.     '-------------------------
  755.     Ready = False
  756.     On Error Resume Next
  757.     temp$ = Dir$(FileToLookFor$)
  758.  
  759.     '------------------------
  760.     ' If not found, start loop
  761.     '------------------------
  762.     If Err <> 0 Or Len(temp$) = 0 Then
  763.     While Not Ready
  764.         Err = 0
  765.         '----------------------------
  766.         ' Put up msg box
  767.         '----------------------------
  768.         Beep
  769.         x = MsgBox("Please insert disk # " + Format$(wDiskNum%), 49, "SETUP")
  770.         If x = 2 Then
  771.         '-------------------------------
  772.         ' Use hit cancel, abort the copy
  773.         '-------------------------------
  774.         PromptForNextDisk = False
  775.         GoTo ExitProc
  776.         Else
  777.         '----------------------------------------
  778.         ' User hits OK, try to find the file again
  779.         '----------------------------------------
  780.         temp$ = Dir$(FileToLookFor$)
  781.         If Err = 0 And Len(temp$) <> 0 Then
  782.             PromptForNextDisk = True
  783.             Ready = True
  784.         End If
  785.         End If
  786.     Wend
  787.     Else
  788.     PromptForNextDisk = True
  789.     End If
  790.  
  791.     
  792.  
  793. ExitProc:
  794.  
  795. End Function
  796.  
  797. Sub RestoreProgMan ()
  798.     On Error GoTo RestoreProgManErr
  799.     AppActivate "Program Manager"   ' Activate Program Manager.
  800.     SendKeys "%{ }{Enter}", True      ' Send Restore keystrokes.
  801. RestoreProgManErr:
  802.     Exit Sub
  803. End Sub
  804.  
  805. '-----------------------------------------------------------------------------
  806. ' Set the Destination File's date and time to the Source file's date and time
  807. '-----------------------------------------------------------------------------
  808. Function SetFileDateTime (SourceFile As String, DestinationFile As String) As Integer
  809.     x = SetTime(SourceFile, DestinationFile)
  810.     SetFileDateTime = -1
  811. End Function
  812.  
  813. Sub UpdateStatus (FileBytes As Long)
  814. '-----------------------------------------------------------------------------
  815. ' Update the status bar using form.control Statusdlg.Picture2
  816. '-----------------------------------------------------------------------------
  817.     Static position
  818.     Dim estTotal As Long
  819.  
  820.     estTotal = Val(Statusdlg.total.Tag)
  821.     If estTotal = False Then
  822.     estTotal = 10000000
  823.     End If
  824.  
  825.     position = position + CSng((FileBytes / estTotal) * 100)
  826.     If position > 100 Then
  827.     position = 100
  828.     End If
  829.     Statusdlg.Picture2.Cls
  830.     Statusdlg.Picture2.Line (0, 0)-((position * (Statusdlg.Picture2.ScaleWidth / 100)), Statusdlg.Picture2.ScaleHeight), QBColor(4), BF
  831.  
  832.     Txt$ = Format$(CLng(position)) + "%"
  833.     Statusdlg.Picture2.CurrentX = (Statusdlg.Picture2.ScaleWidth - Statusdlg.Picture2.TextWidth(Txt$)) \ 2
  834.     Statusdlg.Picture2.CurrentY = (Statusdlg.Picture2.ScaleHeight - Statusdlg.Picture2.TextHeight(Txt$)) \ 2
  835.     Statusdlg.Picture2.Print Txt$
  836.  
  837.     r = BitBlt(Statusdlg.Picture1.hDC, 0, 0, Statusdlg.Picture2.ScaleWidth, Statusdlg.Picture2.ScaleHeight, Statusdlg.Picture2.hDC, 0, 0, SRCCOPY)
  838.  
  839. End Sub
  840.  
  841.